/*****************************************************************************
 * plum_device.h
 *
 * Copyright (C) 2020 Jeasonvor <1101627719@qq.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 ****************************************************************************/

#ifndef __PLUM_DEVICE_H__
#define __PLUM_DEVICE_H__

/*****************************************************************************
 * Included Files
 ****************************************************************************/

/*****************************************************************************
 * Configure Definitions
 ****************************************************************************/

/*****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/** device section name */
#define PLUM_DEVICE_SECTION plum_dev

/*****************************************************************************
 * Public Types
 ****************************************************************************/

/**
 * @brief Device object.
 * This is an opaque data type representing an instance of device.
 */
typedef struct plum_device *plum_device_ref_t;

/**
 * @brief: device power mode.
 */
typedef enum plum_dev_pm {
    /** power off    */
    PLUM_DEV_PM_OFF = 0,

    /** power on     */
    PLUM_DEV_PM_ON = 1,

    /** power sleep  */
    PLUM_DEV_PM_SLEEP = 2,

    /** power wakeup */
    PLUM_DEV_PM_WAKEUP = 3,
} plum_dev_pm_t;

/**
 * @brief: device read message.
 */
typedef struct plum_dev_read {
    plum_u32 offset;
    plum_u8 *rData;
    plum_u16 rSize;
} plum_dev_read_t;

/**
 * @brief: device write message.
 */
typedef struct plum_dev_write {
    plum_u32 offset;
    plum_u8 *wData;
    plum_u16 wSize;
} plum_dev_write_t;

/**
 * @brief: device ioctrl message
 */
typedef struct plum_dev_ioctrl {
    /** operation ID    */
    plum_u32 id;

    /** read pointer    */
    plum_void *rData;

    /** write pointer   */
    plum_void *wData;
} plum_dev_ioctrl_t;

/**
 * @brief Device driver API.
 * API which a device  driver should expose.
 */
typedef struct plum_dev_api {
    /** Method API to init device */
    plum_s32 (*init)(plum_device_ref_t dev);

    /** Method API to deinit device */
    plum_s32 (*fini)(plum_device_ref_t dev);

    /** Method API to reset device */
    plum_s32 (*reset)(plum_device_ref_t dev);

    /** Method API to set power mode to the device */
    plum_s32 (*setpm)(plum_device_ref_t dev, plum_dev_pm_t pm);

    /** Method API to read something */
    plum_s32 (*read)(plum_device_ref_t dev, plum_dev_read_t *arg);

    /** Method API to write something */
    plum_s32 (*write)(plum_device_ref_t dev, plum_dev_write_t *arg);

    /** Method API to control something */
    plum_s32 (*ioctrl)(plum_device_ref_t dev, plum_dev_ioctrl_t *arg);
} plum_dev_api_t;

/**
 * @brief device description.
 */
typedef struct plum_device {
    /**< Device name */
    PLUM_CONST plum_s8 *dev_name;

    /**< Driver  api */
    plum_dev_api_t *dev_api;
} PLUM_SECTION_ALIGNMENT plum_device_t;

/*****************************************************************************
 * Public Data
 ****************************************************************************/

/* use section table record plum_device_t */
PLUM_SECTION_DEF(PLUM_DEVICE_SECTION, plum_device_t);

/**
 * @def PLUM_DEVICE_EXPORT
 * @brief Macro for defining and adding a device.
 *
 * @note All dev_name must have different name.
 *
 * @param[in]: dev_name	    - The device name, No quotes required.
 *                              (e.g. spif - 'spif', spif1 - 'spif1').
 * @param[in]: pub_api	- The driver public api ptr.
 */
#define PLUM_DEVICE_EXPORT(dev_name, pub_api)                         \
    PLUM_SECTION_ITEM_REGISTER(PLUM_DEVICE_SECTION,                   \
                               plum_device_t plum_dev_##dev_name) = { \
        (PLUM_CONST plum_s8 *)PLUM_STRING(dev_name),                  \
        (plum_dev_api_t *)pub_api}

/****************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

/**
 * @brief Init device.
 *
 * @param[in]: dev_name - Device Name.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_init(PLUM_CONST plum_s8 *dev_name);

/**
 * @brief Deinit device.
 *
 * @param[in]: dev_name - Device Name.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_fini(PLUM_CONST plum_s8 *dev_name);

/**
 * @brief Reset device.
 *
 * @param[in]: dev_name - Device Name.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_reset(PLUM_CONST plum_s8 *dev_name);

/**
 * @brief Set power mode to device.
 *
 * @param[in]: dev_name - Device Name.
 * @param[in]: pm       - The power mode.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_setpm(PLUM_CONST plum_s8 *     dev_name,
                           PLUM_CONST plum_dev_pm_t pm);

/**
 * @brief Read message from device.
 *
 * @param[in]: dev_name - Device Name.
 * @param[in]: arg      - Read message pointer.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_read(PLUM_CONST plum_s8 *dev_name, plum_dev_read_t *arg);

/**
 * @brief Write message to device.
 *
 * @param[in]: dev_name - Device Name.
 * @param[in]: arg      - Write message pointer.
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_write(PLUM_CONST plum_s8 *dev_name, plum_dev_write_t *arg);

/**
 * @brief Ctrl device.
 *
 * @param[in]: dev_name - Device Name.
 * @param[in]：arg      - pointer to ioctrl message
 *
 * @return status code that indicates the execution status of the function.
 */
plum_s32 plum_device_ioctrl(PLUM_CONST plum_s8 *dev_name,
                            plum_dev_ioctrl_t * arg);

/**
 * @brief: Init All device.
 *
 * @param:
 *
 * @return status code that indicates the execution status of the function.
 */
plum_void plum_hal_device_init(plum_void);

/****************************************************************************/
#ifdef __cplusplus
}
#endif
/****************************************************************************/
/****************************************************************************/
#endif /* __PLUM_DEVICE_H__ */
/****************************************************************************/

/****************************************************************************/
/*                                                                          */
/*  End of file.                                                            */
/*                                                                          */
/****************************************************************************/
